<?php

use PhpAmqpLib\Connection\AMQPSocketConnection;
use PhpAmqpLib\Message\AMQPMessage;
use PhpAmqpLib\Wire\AMQPTable;
use think\captcha\facade\Captcha;
use think\facade\Db;
use think\facade\Log;
use think\response\Json;

// 应用公共文件
function jsonReturn($code, $msg = '', $data = [], $statusCode = 200): Json
{
    $result = [
        'code' => $code ? 0 : 1,
        'message' => $msg,
        'result' => $data
    ];
    return json($result, $statusCode);
}

function randomStr($len = 4): string
{
    $strs = str_shuffle('abcdefghijklmnopqrstuvwxyzABCDEFGKIJKLMNOPQRSTUVWXYZ0123456789');
    $strArr = str_split($strs);
    $result = [];
    for ($i = 0; $i < $len; $i++) {
        $result[] = $strArr[$i];
    }
    return implode('', $result);
}

function commonRecursion($list, int $pid = 0, int $level = 0, string $col = 'pid', string $sub = 'child', bool $ept = false): array
{
    $result = [];
    foreach ($list as $key => $val) {
        if ($val[$col] == $pid) {
            $val[$sub] = commonRecursion($list, $val['id'], $level++, $col, $sub);
            if (empty($val[$sub]) && $ept) unset($val[$sub]);
            $result[] = $val;
            unset($list[$key]);
        }
    }

    return $result;
}

function hexToAscii(string $string): string
{
    $result = '';
    for ($i = 0; $i < strlen($string) - 1; $i += 2) {
        $result .= chr(hexdec($string[$i] . $string[$i + 1]));
    }

    return $result;
}

function crc8($ar = "", $inverse = false): string
{
    $len = strlen($ar);                  //取出字符长度
    if ($len < 4) {
        return "";
    }

    $data = substr($ar, 0, 2);        //取出第一个字节的两个字符
    $data = hexdec($data);               //转换为10进制
    for ($i = 2; $i < $len; $i += 2) {
        $data_t = substr($ar, $i, 2);      //取出后续字符
        $data_t = hexdec($data_t);            //转换为10进制

        $data = $data ^ $data_t;         //按位取异或
    }
    //转换为16进制
    return $inverse ? substr(sprintf("%02x", ~$data), -2) : sprintf("%02x", $data);
}

/**
 * 说明：计算校验和(CRC16 2字节)
 * https://blog.csdn.net/weixin_39442130/article/details/106714734
 * @param $string
 * @return string
 */
function crc16($string, $hex = true)
{
    $string = pack('H*', $string);
    $crc = 0xFFFF;
    for ($x = 0; $x < strlen($string); $x++) {
        $crc = $crc ^ ord($string[$x]);
        for ($y = 0; $y < 8; $y++) {
            if (($crc & 0x0001) == 0x0001) {
                $crc = (($crc >> 1) ^ 0xA001);
            } else {
                $crc = $crc >> 1;
            }
        }
    }

    if ($hex) {
        $low = dechex($crc % 256);
        $height = dechex((int)floor($crc / 256));
        $low = str_pad($low, 2, '0', STR_PAD_LEFT);
        $height = str_pad($height, 2, '0', STR_PAD_LEFT);
        return $low . $height;
    } else {
        return $crc;
    }
}

function rabbitmqConnect()
{
    try {
        $host = env('rabbitmq.mq_host');
        $port = env('rabbitmq.mq_port');
        $userName = env('rabbitmq.mq_username');
        $password = env('rabbitmq.mq_password');
        $queueName = env('rabbitmq.mq_queue_name');
        $exchangeName = env('rabbitmq.mq_exchange_name');
        $routeKey = env('rabbitmq.mq_route_key');
        $vhost = env('rabbitmq.mq_vhost');

        $connection = new AMQPSocketConnection($host, $port, $userName, $password, $vhost, false, 'AMQPLAIN', null, 'en_US', 3.0, true, null, 60);
        $channel = $connection->channel();

        $channel->exchange_declare($exchangeName, 'direct', false, true, false);

        $channel->queue_declare($queueName, false, true, false, false, false, new AMQPTable([
            'x-message-ttl' => 86400000, //消息存活时间，单位毫秒
        ]));
        $channel->queue_bind($queueName, $exchangeName, $routeKey);

        return $channel;
    } catch (Exception $e) {
        Log::write('[error]rabbitmq连接错误：' . $e->getMessage(), 'error');
        return false;
    }
}

function rabbitmqPush($data)
{
    try {
        $channel = rabbitmqConnect();
        if (!$channel) {
            return false;
        }

        $exchangeName = env('rabbitmq.mq_exchange_name');
        $routeKey = env('rabbitmq.mq_route_key');

        $message = new AMQPMessage($data);
        $channel->basic_publish($message, $exchangeName, $routeKey);

        //$channel->basic_consume($queueName, '', false, false, false, false, [$this, 'consume']);
        return $channel;
    } catch (Exception $e) {
        Log::write('[error]rabbitmq数据推送错误：' . $e->getMessage(), 'error');
        return false;
    }
}

function createFrozenDataTable($timestamp = null)
{
    try {
        $date = date('Y_m', $timestamp ?? time());
        $tableName = "ice_data_{$date}";
        $tables = Db::getTables();
        if (in_array($tableName, $tables)) {
            return true;
        }

        $schema = "CREATE TABLE `{$tableName}` (
          `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
          `serial_number` char(50) NOT NULL DEFAULT '',
          `medium_thickness` char(255) NOT NULL DEFAULT '',
          `temperature` char(255) NOT NULL DEFAULT '',
          `device_num` char(255) NOT NULL DEFAULT '',
          `water_film` char(255) NOT NULL DEFAULT '',
          `smoothness` char(255) NOT NULL DEFAULT '',
          `original` varchar(1024) NOT NULL DEFAULT '',
          `receive_time` datetime DEFAULT NULL,
          `create_time` datetime DEFAULT NULL,
          `update_time` datetime DEFAULT NULL,
          `delete_time` datetime DEFAULT NULL,
          PRIMARY KEY (`id`),
          KEY `id` (`id`)
        ) ENGINE=MyISAM AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4;";

        Db::execute($schema);
        return true;
    } catch (\Exception $e) {
        return false;
    }
}


function microUnique(): string
{
    return ceil(microtime(true) * 1000);
}

function generateCaptchaBase64($type = 'verify'): string
{
    try {
        $captcha = Captcha::create($type, true);
        return base64_encode($captcha->getData());
    } catch (Exception $e) {
        return false;
    }
}


function parseData($data, $serialNumber)
{
    try {
        if (!$data) {
            return false;
        }

        $dataStr = str_replace([' '], '', $data);
        $result[] = hexdec(substr($dataStr, 4, 8));
        $dataStr = substr($dataStr, 12);
        $dataArray = str_split($dataStr, 4);

        foreach ($dataArray as $value) {
            $result[] = hexdec($value);
        }

        $mediumThickness = $result[0] ?? 0;
        $temperature = $result[1] ?? 0;
        $deviceNum = $result[2] ?? 0;
        $waterFilm = $result[3] ?? 0;
        $smoothness = $result[4] ?? 0;

        $temperature = $temperature ? round($temperature / 10, 2) : 0;
        if ($temperature >= 5 && $mediumThickness > 0) {
            $mediumThickness = 0;
        }

        if ($mediumThickness > 200 || abs($temperature) > 50) {
            return false;
        }

        return [
            'medium_thickness' => $mediumThickness,
            'temperature' => $temperature,
            'device_num' => $deviceNum,
            'water_film' => $waterFilm,
            'smoothness' => $smoothness,
        ];
    } catch (Exception $e) {
        return [];
    }
}

function transferValidate(array $data): bool
{
    try {
        $validate = true;
        $mediumThickness = $data['medium_thickness'] ?? 0;
        $temperature = $data['temperature'] ?? 0;
        $waterFilm = $data['water_film'] ?? 0;
        $smoothness = $data['smoothness'] ?? 0;

        if ($mediumThickness + $temperature + $waterFilm + $smoothness == 0) {
            $validate = false;
        }

        if (abs($mediumThickness) > 10000) {
            $validate = false;
        }

        if (abs($temperature) > 50) {
            $validate = false;
        }

        if (abs($waterFilm) > 300) {
            $validate = false;
        }

        if (abs($smoothness) > 10000) {
            $validate = false;
        }

        return $validate;
    } catch (Exception $e) {
        return false;
    }
}


function hexToString(string $string): string
{
    $result = '';
    for ($i = 0; $i < strlen($string) - 1; $i += 2) {
        $result .= chr(hexdec($string[$i] . $string[$i + 1]));
    }

    return $result;
}

function stringToHex($str): string
{
    $hex = '';
    for ($i = 0; $i < strlen($str); $i++) {
        $hex .= dechex(ord($str[$i]));
    }

    return $hex;
}